import de.medieninf.ads.ADSTool;

public class Aufgabe2 {

	/**
	 * @param args
	 * 
	 */

	/**
	 * Returns the max-Value of two integer-values
	 * 
	 * @param x
	 *            the first integer-value
	 * @param y
	 *            the second integer-value
	 */

	public static int max(int x, int y) {

		if (x > y)
			return x;
		else
			return y;

	}

	/**
	 * Returns the min-Value of two integer-values
	 * 
	 * @param x
	 *            the first integer-value
	 * @param y
	 *            the second integer-value
	 * @return
	 */

	public static int min(int x, int y) {
		if (x > y)
			return y;
		else
			return x;
	}

	/**
	 * Returns the smallest Value inside a specific field range
	 * 
	 * @param xMin
	 * @param xMax
	 * @param yMin
	 * @param yMax
	 * @param x
	 * @param y
	 * @param sourceField
	 * @return
	 */

	public static int getSmallestValue(int xMin, int xMax, int yMin, int yMax,
			int x, int y, int[][] sourceField) {

		// Set the smallest Value to the center-point of the field range
		int smallestValue = sourceField[x][y];

		// Check if there is a smaller value in a field around the center-point
		for (int i = xMax; i < xMin; i++) {

			for (int j = yMax; j < yMin; j++) {

				if (sourceField[i][j] < smallestValue) {
					smallestValue = sourceField[i][j];

				}
			}
		}
		return smallestValue;

	}

	/**
	 * Converts a two-dimensional array of a one-dimensional array, containing a
	 * pgm-file
	 * 
	 * @param sourceImage
	 * @return
	 */

	public static int[][] getField(int[] sourceImage) {

		// Create a new to-dimensional field with the size of the source image
		int[][] returnField = new int[sourceImage[0]][sourceImage[1]];

		// Set the counter to 3, to ignore the default values at the beginning
		// of the image-array (height, etc.)
		int sourceCounter = 3;

		// Write the image-file values to the two-dimensional array
		for (int i = 0; i < sourceImage[0]; i++) {
			for (int j = 0; j < sourceImage[1]; j++) {

				returnField[i][j] = sourceImage[sourceCounter];
				sourceCounter++;
			}
		}

		return returnField;

	}

	/**
	 * Converts a two-dimensional array to a one-dimensional pgm-file array
	 * 
	 * @param sourceField
	 * @param sourceImage
	 * @return
	 */

	public static int[] getArray(int[][] sourceField, int[] sourceImage) {

		// Create a new array with the length of the original image-file
		int[] returnField = new int[sourceImage.length];

		// Copy the default values from the original image-file to the new
		// image-file (height, etc.)
		returnField[0] = sourceImage[0];
		returnField[1] = sourceImage[1];
		returnField[2] = sourceImage[2];

		// Set the counter to 3, to ignore the default values (height, etc.)
		int arrayCounter = 3;

		// Copy every image-value to the new image-file
		for (int i = 0; i < sourceImage[0]; i++) {

			for (int j = 0; j < sourceImage[1]; j++) {
				returnField[arrayCounter] = sourceField[i][j];
				arrayCounter++;
			}
		}

		return returnField;

	}

	/**
	 * Converts a pgm-file to a brighter version
	 * 
	 * @param sourceImage
	 * @param p
	 * @return
	 */
	public static int[] heller(int[] sourceImage, int p) {

		// Create a new two-dimensional field and put the original pgm image
		// into it
		int sourceField[][] = getField(sourceImage);

		// Create a new two-dimensional field with the size of the original pgm
		// image, to put
		// the new image into it
		int targetField[][] = new int[sourceImage[0]][sourceImage[1]];

		// Calculate the new brightnes around the given range (p)
		for (int x = 0; x < sourceImage[0] - 1; x++) {
			for (int y = 0; y < sourceImage[1]; y++) {

				int xMin = min((sourceImage[1] - 1), x + (int) (p / 2));
				int xMax = max(0, x - (int) (p / 2));
				int yMin = min((sourceImage[0] - 1), y + (int) (p / 2));
				int yMax = max(0, y - (int) (p / 2));

				// Write the smallest value to the target image-file

				targetField[x][y] = getSmallestValue(xMin, xMax, yMin, yMax, x,
						y, sourceField);

			}
		}

		System.out.println("Edited Image: heller " + p + " ");

		// Convert the two-dimensional field with the new pgm image file
		return getArray(targetField, sourceImage);

	}

	// public static double addSum(double sum, double value) {
	//
	// return sum = sum+value;
	// }
	//
	// public static double addSum(double sum, double value) {
	//
	// return sum = sum+value;
	// }

	public static int[] kanten(int[] sourceImage, int p) {

		int sourceField[][] = getField(sourceImage);
		int targetField[][] = new int[sourceField.length][sourceField.length];
		int matrixA[][] = new int[][] { { 1, 0, -1 }, { 2, 0, -2 },
				{ 1, 0, -1 } };
		int matrixB[][] = new int[][] { { 1, 2, 1 }, { 0, 0, 0 },
				{ -1, -2, -1 } };
		double sumA = 0.00;
		double sumB = 0.00;

		for (int i = 0; i <= 2; i++) {
			for (int j = 0; j <= 2; j++) {
//				System.out.print(matrixA[i][j]);
			}
		}

		for (int i = 0; i <= 2; i++) {
			for (int j = 0; j <= 2; j++) {
//				System.out.print(matrixB[i][j]);
			}
		}

		for (int x = 1; x < sourceImage[0] - 1; x++) {
			for (int y = 1; y < sourceImage[1] - 1; y++) {

				sumA = (sourceField[x - 1][y - 1] * matrixA[0][0])
						+ (sourceField[x][y - 1] * matrixA[1][0])
						+ (sourceField[x + 1][y - 1] * matrixA[2][0])
						+ (sourceField[x - 1][y] * matrixA[0][1])
						+ (sourceField[x][y] * matrixA[1][1])
						+ (sourceField[x + 1][y] * matrixA[2][1])
						+ (sourceField[x - 1][y + 1] * matrixA[0][2])
						+ (sourceField[x][y + 1] * matrixA[1][2])
						+ (sourceField[x + 1][y + 1] * matrixA[2][2]);

				sumB = (sourceField[x - 1][y - 1] * matrixB[0][0])
						+ (sourceField[x][y - 1] * matrixB[1][0])
						+ (sourceField[x + 1][y - 1] * matrixB[2][0])
						+ (sourceField[x - 1][y] * matrixB[0][1])
						+ (sourceField[x][y] * matrixB[1][1])
						+ (sourceField[x + 1][y] * matrixB[2][1])
						+ (sourceField[x - 1][y + 1] * matrixB[0][2])
						+ (sourceField[x][y + 1] * matrixB[1][2])
						+ (sourceField[x + 1][y + 1] * matrixB[2][2]);

				//
				// sumA = addSum(sumA,sourceField[x-1][y-1] * matrixA[0][0]);
				// sumA = addSum(sumA,sourceField[x][y-1] * matrixA[1][0]);
				// sumA = addSum(sumA,sourceField[x+1][y-1] * matrixA[2][0]);
				// sumA = addSum(sumA,sourceField[x-1][y] * matrixA[0][1]);
				// sumA = addSum(sumA,sourceField[x][y] * matrixA[1][1]);
				// sumA = addSum(sumA,sourceField[x+1][y] * matrixA[2][1]);
				// sumA = addSum(sumA,sourceField[x-1][y+1] * matrixA[0][2]);
				// sumA = addSum(sumA,sourceField[x][y+1] * matrixA[1][2]);
				// sumA = addSum(sumA,sourceField[x+1][y+1] * matrixA[2][2]);
				//
				// sumB = addSum(sumB,sourceField[x-1][y-1] * matrixB[0][0]);
				// sumB = addSum(sumB,sourceField[x][y-1] * matrixB[1][0]);
				// sumB = addSum(sumB,sourceField[x+1][y-1] * matrixB[2][0]);
				// sumB = addSum(sumB,sourceField[x-1][y] * matrixB[0][1]);
				// sumB = addSum(sumB,sourceField[x][y] * matrixB[1][1]);
				// sumB = addSum(sumB,sourceField[x+1][y] * matrixB[2][1]);
				// sumB = addSum(sumB,sourceField[x-1][y+1] * matrixB[0][2]);
				// sumB = addSum(sumB,sourceField[x][y+1] * matrixB[1][2]);
				// sumB = addSum(sumB,sourceField[x+1][y+1] * matrixB[2][2]);
				//

				if (sumA < 0)
					sumA = sumA * (-1);
				if (sumB < 0)
					sumB = sumB * (-1);

				targetField[x - 1][y - 1] = (int) (sumA + sumB) / 5;

			}
		}
		System.out.println("Edited Image: kanten " + p + " ");
//		System.out.println("sumA " + sumA);
//		System.out.println("sumB " + sumB);
		return getArray(targetField, sourceImage);

	}

	public static void main(String[] args) {

		if (args.length < 4) {
			System.out.println("Not enought arguments!");
		} else {

			String function = args[0];
			String value = args[1];
			String sourceFile = args[2];
			String targetFile = args[3];

			int[] sourceImage = ADSTool.readPGM(sourceFile);
			int[] targetImage = new int[sourceImage.length];
			int p = Integer.valueOf(value);

			if (function.equals("heller")) {
				if (p % 2 == 0) {
					System.out.println("Parameter nicht ungerade! ");
				} else {
					targetImage = heller(sourceImage, p);
					ADSTool.savePGM(targetFile, targetImage);
				}

			} else if (function.equals("kanten")) {
				targetImage = kanten(sourceImage, p);
				ADSTool.savePGM(targetFile, targetImage);
			}

		}
	}

}
